package ru.hh.team02.chat.client;

import ru.hh.team02.chat.messaging.Message;
import ru.hh.team02.chat.messaging.SendingQueue;
import ru.hh.team02.chat.server.ChatServer;
import ru.hh.team02.chat.utils.StringSocket;

import java.io.IOException;
import java.net.Socket;

/**
 * class fully responsible for communicating with client computer
 */
public class Client implements Runnable {

    private StringSocket socket;
    private String name = "";
    private SendingQueue sendingQueue = new SendingQueue(1, this);

    /**
     * Create empty client for testing purposes.
     */
    public Client(String name) {
        this.name = name;
    }

    public Client(Socket socket) {
        this.socket = new StringSocket(socket);
    }

    public String getName() {
        return name;
    }

    public String getRoom() {
        return ChatServer.registry.getClientRoom(getName());
    }

    @Override
    public void run() {
        try {
            socket.write("connected");
            ChatServer.adminLogger.Write("New client has connected");

            registerClient();

            String message = "";
            do {
                message = socket.read();
                handleMessage(message);
            } while (!message.equals("exit"));
            ChatServer.adminLogger.Write("Client \"" + this.name
                    + "\" has disconnected");
        } catch (IOException e) {
            System.out.println("client went down");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sendingQueue.terminate();
            ChatServer.registry.deleteClient(this);
            socket.close();
        }
    }

    /**
     * sends message to client. CAN BLOCK HERE!!!
     */
    public void sendMessageToClientComputer(Message message) {
        try {
            socket.write(message.getText());
        } catch (IOException e) {

        }
    }

    /**
     * 
     */
    private void handleMessage(String message) {

        if (message.startsWith("change")) {
            String[] info = message.split(" ");
            if (info.length == 2) {
                ChatServer.registry.changeRoom(this, info[1]);
                ChatServer.adminLogger.Write("Client \"" + this.name
                        + "\" entered in new room \"" + info[1] + "\"");
            }
        } else {
            ChatServer.adminLogger.Write("Client \"" + this.name
                    + "\" sent new message: \"" + message + "\"");
            ChatServer.messanger.sendMessageToRoom(name + "> " + message,
                    getName());
        }
    }

    // ------------------------------------------ AUTHENTIFICATION METHODS

    /**
     * asks room and name. saves to registry
     */
    private void registerClient() throws IOException {
        String room;
        do {
            socket.write("Room: "
                    + ChatServer.registry.getRoomNames().toString());
            socket.write("Input room name");
            room = socket.read();
        } while (!ChatServer.registry.hasRoom(room));
        ChatServer.adminLogger.Write("New client entered in \"" + room + "\"");
        socket.write("Ok");
        do {
            socket.write("Input login");

            // At this point the client is not registered anywhere
            // and won't be accessed by anybody.
            // So it's OK to have their name not matching the
            // client registry.
            this.name = socket.read();
        } while (this.name.length() > 0
                && !ChatServer.registry.addClient(this, room));
        ChatServer.adminLogger.Write("New client is \"" + this.name + "\"");
        socket.write("Ok");
    }

    public boolean add(Message message) {
        return sendingQueue.add(message);

    }

}
